package com.lt.lumentracks.controller.websocket;

import jakarta.websocket.OnClose;
import jakarta.websocket.OnMessage;
import jakarta.websocket.OnOpen;
import jakarta.websocket.*;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

@Component
@Slf4j
@ServerEndpoint("/ws/groupChat/{token}") // 连接路径 -- ws://localhost:8080/ws/groupChat/${token}
public class WebSocketServer_groupChat {

    // 房间 -> 会话集合
    private static final ConcurrentHashMap<String, Set<Session>> ROOMS = new ConcurrentHashMap<>();

    // 1. 连进来
    @OnOpen
    public void onOpen(Session session, @PathParam("token") String token) {
        // 根据 token 拿到房间号（这里 token 就是房间号）
        ROOMS.computeIfAbsent(token, k -> ConcurrentHashMap.newKeySet()).add(session);
        log.info("【系统】{} 加入了房间", token);
        // broadcast(token, "【系统】" + session.getId() + " 加入了房间");
    }

    // 2. 收到消息
    @OnMessage
    public void onMessage(String msg, Session session, @PathParam("token") String token) {
        log.info("收到消息: token={}, message={}", token, msg);

        // 把“某人”发的消息广播给同房间所有人
        broadcast(token, msg);
    }

    // 3. 断开
    @OnClose
    public void onClose(Session session, @PathParam("token") String token) {
        Set<Session> room = ROOMS.get(token);
        if (room != null) {
            room.remove(session);
            if (room.isEmpty()) ROOMS.remove(token);
        }
        log.info("【系统】{} 离开了房间", token);
        // broadcast(token, "【系统】" + session.getId() + " 离开了房间");
    }

    // 广播
    private static void broadcast(String token, String msg) {
        Set<Session> room = ROOMS.get(token);
        if (room == null) return;
        // 异步发送，失败就关闭
        room.parallelStream().forEach(s -> {
            if (s.isOpen()) {
                try {
                    s.getBasicRemote().sendText(msg);
                } catch (IOException e) {
                    try { s.close(); } catch (IOException ignore) {}
                }
            }
        });
    }

}
